
import { ExecutiveContext, State,Executive, Autherizable, ActivityStatus, ExecuteStatus } from "../defination"
import { ActivityRecord, ByteArray, ExecutionRecord, ExecutiveRecord } from "../entity"
import {  ACTIVITY, ACTIVITY_STATUS, DEALER, EXECUTION_RECORD,  NEXT, EXECUTE_STATUS, REQUEST, RESULT, STATE_RECORD } from "../shared-symbols"
import { BaseAction } from "./action"
import type { DealAction } from "./dealAction"
import { ExitAction } from "./exitAction"

const ENDED = Symbol('ended')
export class EndAction
<
  TActivity extends Executive<TActivity,TState,TRecord,TContext>,
  TState extends State=State,
  TRecord extends ExecutiveRecord=ExecutiveRecord,
  TContext extends ExecutiveContext=ExecutiveContext
> extends BaseAction<TActivity,TState,TRecord,TContext>
{
  [ENDED]?:boolean
  constructor(act:BaseAction<TActivity,TState,TRecord,TContext>){
    super(act)
  }
  public get ended():boolean{
    return this[ENDED]===true
  }
  async invoke(context:TContext):Promise<BaseAction<TActivity,TState,TRecord,TContext>|undefined>{
    if (this[ENDED]===true)
      throw new Error('end action can only be invoked once')

    this[ENDED] = true
    const activity = this[ACTIVITY]

    activity[EXECUTE_STATUS] = ExecuteStatus.FINISHED

    const at = context.calendar.now()
    const dealerId = context[DEALER].id
    const finishBytes = context.enumConverter.toByteArray<ByteArray>(ExecuteStatus.FINISHED,ExecuteStatus,true)!

    
    const activityRecord = this[STATE_RECORD] as unknown as ActivityRecord
    activityRecord.executeStatus = finishBytes
    activityRecord.executionId = undefined!
    activityRecord.modifierId = dealerId
    activityRecord.updateTime = at

    const executionRecord = this[EXECUTION_RECORD] as ExecutionRecord
    executionRecord.executeStatus = finishBytes
    executionRecord.updateTime = at
    executionRecord.overTime = at

    await context.repository.endActivity(
      activityRecord,
      executionRecord,
      context[REQUEST].requestId
    )
    return this.next!
  }

  get next():null| undefined{
    if (this[NEXT]===undefined){
      if (this[ENDED]===undefined){
        return undefined
      }else {
        return this[NEXT] = null
      }
    }
    return this[NEXT] as null | undefined
  }
}